# 类型模块
from PyQt6.QtWidgets import (
    QWidget,
    QCheckBox,
    QComboBox,
    QLineEdit,
    QSpinBox,
    QHBoxLayout,
)
from PyQt6.QtGui import QValidator
from PyQt6.QtCore import Qt
from typing import Optional, Any


class HexValidator(QValidator):
    """十六进制验证器"""

    def validate(self, input_str: str, pos: int) -> tuple[QValidator.State, str, int]:
        if not input_str:
            return (QValidator.State.Acceptable, input_str, pos)

        if input_str.startswith("0x"):
            input_str = input_str[2:]

        for c in input_str:
            if not c.lower() in "0123456789abcdef":
                return (QValidator.State.Invalid, input_str, pos)

        return (QValidator.State.Acceptable, input_str, pos)


class TypeModule:
    """类型模块 - 处理不同类型的配置控件"""

    @staticmethod
    def create_control(
        config_type: str, initial_value: Optional[Any] = None
    ) -> tuple[QWidget, QWidget]:
        """
        创建配置控件
        返回：(容器widget, 主要输入控件)
        """
        container = QWidget()
        layout = QHBoxLayout(container)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(4)

        control: QWidget = QWidget()

        if config_type == "bool":
            control = QCheckBox()
            if initial_value is not None:
                try:
                    v = initial_value
                    if isinstance(v, str):
                        v = v.strip().lower() in {"y", "yes", "true", "1"}
                    else:
                        v = bool(v)
                    control.setChecked(v)
                except Exception:
                    # Fallback: unchecked if value cannot be coerced
                    control.setChecked(False)

        elif config_type == "tristate":
            control = QComboBox()
            control.addItems(["N (No)", "M (Module)", "Y (Yes)"])
            if initial_value is not None:
                if initial_value == "y":
                    control.setCurrentIndex(2)
                elif initial_value == "m":
                    control.setCurrentIndex(1)
                else:
                    control.setCurrentIndex(0)

        elif config_type == "string":
            control = QLineEdit()
            if initial_value is not None:
                control.setText(str(initial_value))

        elif config_type == "int":
            control = QSpinBox()
            control.setRange(-2147483647, 2147483647)
            if initial_value is not None:
                control.setValue(int(initial_value))

        elif config_type == "hex":
            control = QLineEdit()
            control.setValidator(HexValidator())
            if initial_value is not None:
                try:
                    if isinstance(initial_value, str):
                        text = initial_value.replace("0x", "").replace("0X", "")
                        control.setText(f"0x{int(text, 16):X}")
                    else:
                        control.setText(f"0x{int(initial_value):X}")
                except Exception:
                    control.setText("")

        layout.addWidget(control)
        return container, control

    @staticmethod
    def get_control_value(config_type: str, control: QWidget) -> Any:
        """获取控件的值"""
        if config_type == "bool":
            return control.isChecked() if isinstance(control, QCheckBox) else False

        elif config_type == "tristate":
            if isinstance(control, QComboBox):
                index = control.currentIndex()
                return ["n", "m", "y"][index]
            return "n"

        elif config_type == "string":
            return control.text() if isinstance(control, QLineEdit) else ""

        elif config_type == "int":
            return control.value() if isinstance(control, QSpinBox) else 0

        elif config_type == "hex":
            if isinstance(control, QLineEdit):
                text = control.text().replace("0x", "").replace("0X", "")
                return int(text, 16) if text else 0
            return 0

        return None

    @staticmethod
    def set_control_value(config_type: str, control: QWidget, value: Any) -> None:
        """设置控件的值"""
        if config_type == "bool" and isinstance(control, QCheckBox):
            try:
                v = value
                if isinstance(v, str):
                    v = v.strip().lower() in {"y", "yes", "true", "1"}
                else:
                    v = bool(v)
                control.setChecked(v)
            except Exception:
                control.setChecked(False)

        elif config_type == "tristate" and isinstance(control, QComboBox):
            if value == "y":
                control.setCurrentIndex(2)
            elif value == "m":
                control.setCurrentIndex(1)
            else:
                control.setCurrentIndex(0)

        elif config_type == "string" and isinstance(control, QLineEdit):
            control.setText(str(value))

        elif config_type == "int" and isinstance(control, QSpinBox):
            control.setValue(int(value))

        elif config_type == "hex" and isinstance(control, QLineEdit):
            try:
                if isinstance(value, str):
                    text = value.replace("0x", "").replace("0X", "")
                    control.setText(f"0x{int(text, 16):X}")
                else:
                    control.setText(f"0x{int(value):X}")
            except Exception:
                control.setText("")

    @staticmethod
    def set_control_enabled(control: QWidget, enabled: bool) -> None:
        """设置控件启用状态"""
        control.setEnabled(enabled)
